﻿using System;


namespace S
{

    //一、什么是状态模式？
    //状态模式（State Pattern）是一种行为型设计模式，核心思想是：
    //将对象的状态封装成独立的类，当对象内部状态改变时，自动切换到对应的行为逻辑，而不是用大量的 if-else 或 switch。
    //通俗理解：
    //就像交通灯从红变绿，它的行为随状态变化而变化，但你不需要用 if/else 来写红灯、绿灯的行为逻辑，而是交给不同的“状态类”去处理。

    //二、适用场景
    //你应该在以下情况使用状态模式：
    //一个对象的行为依赖于它的当前状态，并且行为会随状态改变而改变。
    //代码中充满了基于状态的 if-else 或 switch-case 逻辑。
    //状态逻辑复杂，希望将每个状态的行为封装、隔离，以便维护和扩展。

    //三、结构组成（UML）
    //      角色                                          描述
    //Character（某个角色）	           状态持有者，维护当前状态对象，并定义对外接口
    //ICharacterState（抽象状态）	       定义所有具体状态的公共行为接口
    //ConcreteState（具体状态）	       实现不同状态下的行为逻辑，并可能切换状态


    //四、示例：游戏角色状态（站立、跳跃、攻击状态切换）


    //五、优缺点分析
    //✅ 优点
    //遵循开闭原则：新增状态只需新建类，不修改已有代码。
    //将复杂状态逻辑分散到各个状态类，清晰且可维护。

    //避免使用大量 if-else 或 switch 语句，代码更简洁。


    //六、实际应用场景
    //  场景                      示例
    //UI 组件           按钮：正常、悬停、禁用、按下状态
    //工作流引擎         订单状态：待付款、已发货、已取消等
    //游戏开发          角色状态：行走、跳跃、受伤、死亡等
    //Revit/CAD插件     工具面板状态：选择线、绘制线、编辑线
    //网络连接          TCP状态机（CLOSED、LISTEN、ESTABLISHED...）


    //七、状态模式 vs 策略模式 的区别
    // 模式                  意图               是否感知上下文             状态切换
    //状态模式      根据状态变化自动改变行为        ✅ 有	                ✅ 有状态自动切换逻辑
    //策略模式      封装一组可互换算法	             ❌ 无	                ❌由外部控制切换


    //八、总结一句话
    //当对象在不同状态下有不同的行为，并且状态之间需要自动切换时，使用状态模式可以让你的代码更清晰、更符合面向对象设计原则。


    /// <summary>
    /// 抽象状态接口-游戏角色的动作(角色状态接口)
    /// </summary>
    public interface ICharacterState
    {
        void Handle(Character context);
    }


    /// <summary>
    /// 角色类
    /// </summary>
    public class Character
    {
        private ICharacterState _state;

        public Character(ICharacterState state)
        {
            _state = state;
        }

        /// <summary>
        /// 设置对象的状态
        /// </summary>
        /// <param name="state">角色状态接口,可以传入不同的状态实例</param>
        public void SetState(ICharacterState state)
        {
            _state = state;
        }

        public void Action()
        {
            _state.Handle(this);
        }
    }



    #region 具体状态类

    /// <summary>
    /// 站立状态
    /// </summary>
    public class StandingState : ICharacterState
    {
        public void Handle(Character context)
        {
            Console.WriteLine("角色处于【站立】状态");

            //从站立状态切换到 跳跃状态
            context.SetState(new JumpingState());
        }
    }

    /// <summary>
    /// 跳跃状态
    /// </summary>
    public class JumpingState : ICharacterState
    {
        public void Handle(Character context)
        {
            Console.WriteLine("角色处于【跳跃】状态");
            //从【跳跃】状态切换到【攻击】状态 ---状态切换
            context.SetState(new AttackingState());
        }
    }

    /// <summary>
    /// 攻击状态
    /// </summary>
    public class AttackingState : ICharacterState
    {
        public void Handle(Character context)
        {
            Console.WriteLine("角色处于【攻击】状态");

            //从【攻击】状态切换到【站立】状态
            context.SetState(new StandingState());
        }
    }
    #endregion




    class Program
    {
        static void Main(string[] args)
        {
            //func1();

            func2();

            Console.ReadKey();
        }


        static void func1()
        {
            Context context = new Context();
            context.SetState(new StateB());
            context.Request();
        }


        static void func2()
        {
            //定义初始状态
            Character player = new Character(new StandingState());

            player.Action(); // 站立 -> 跳跃
            player.Action(); // 跳跃 -> 攻击
            player.Action(); // 攻击 -> 站立

            player.Action(); // 站立 -> 跳跃
        }
    }
}
